package com.ruoyi.predict.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.ruoyi.predict.controller.PredictionController;
import com.ruoyi.predict.domain.BoleScriptPredictionRecord;
import com.ruoyi.predict.mapper.BoleScriptPredictionRecordMapper;
import com.ruoyi.predict.service.PredictByHuaWeiService;
import com.ruoyi.predict.utils.ScoreJsonParser;
import com.ruoyi.predict2.domain.BoleScriptPredictionRecord2;
import com.ruoyi.predict2.mapper.BoleScriptPredictionRecord2Mapper;
import com.ruoyi.resume.domain.BoleResumeEducation;
import com.ruoyi.resume.domain.BoleResumeProject;
import com.ruoyi.resume.domain.BoleResumeSkills;
import com.ruoyi.resume.domain.BoleResumeWork;
import com.ruoyi.resume.dto.ResumeDTO;
import com.ruoyi.resume.service.IResumeService;
import dev.langchain4j.data.message.ChatMessage;
import dev.langchain4j.data.message.UserMessage;
import dev.langchain4j.model.ollama.OllamaChatModel;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.net.ssl.*;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.io.IOException;
import java.time.Duration;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class PredictByHuaWeiServiceImpl implements PredictByHuaWeiService {

    @Autowired
    private BoleScriptPredictionRecordMapper boleScriptPredictionRecordMapper;
    @Autowired
    private BoleScriptPredictionRecord2Mapper boleScriptPredictionRecordMapper2;
    @Autowired
    private IResumeService resumeService;

    private static final Logger logger = LoggerFactory.getLogger(PredictionController.class);
    // 实际执行预测逻辑的方法
    @Override
    @Async("asyncExecutor") // 指定使用名为 asyncExecutor 的线程池
    @Transactional
    public void executePrediction(Long userId) {
        try {
            BoleScriptPredictionRecord predictionRecord = boleScriptPredictionRecordMapper.selectBoleScriptPredictionRecordByUserId(userId);
            ResumeDTO boleResumes = resumeService.getResume(userId);

            if (boleResumes == null) {
                logger.warn("用户[{}]未找到简历信息，无法进行岗位预测", userId);
                return;
            }

            // 构建prompt（基于实际实体类结构）
            // 1. 处理技能（BoleResumeSkills列表，提取skillName）
            StringBuilder skillsSb = new StringBuilder();
            if (boleResumes.getSkills() != null && !boleResumes.getSkills().isEmpty()) {
                for (BoleResumeSkills skill : boleResumes.getSkills()) {
                    if (skill != null && skill.getSkillName() != null) {
                        if (skillsSb.length() > 0) {
                            skillsSb.append("、"); // 用顿号分隔多个技能
                        }
                        skillsSb.append(skill.getSkillName());
                    }
                }
            }
            String skills = skillsSb.length() > 0 ? skillsSb.toString() : "无";

            // 2. 处理教育经历（BoleResumeEducation列表，拼接学历、学校、专业）
            StringBuilder educationSb = new StringBuilder();
            if (boleResumes.getEducations() != null && !boleResumes.getEducations().isEmpty()) {
                for (BoleResumeEducation edu : boleResumes.getEducations()) {
                    if (edu != null) {
                        // 跳过空的教育记录
                        if (edu.getDegree() == null && edu.getSchool() == null) {
                            continue;
                        }
                        // 拼接格式：学历（学校，专业）
                        StringBuilder eduItem = new StringBuilder();
                        if (edu.getDegree() != null) {
                            eduItem.append(edu.getDegree());
                        }
                        if (edu.getSchool() != null) {
                            eduItem.append("（").append(edu.getSchool());
                            // 补充专业（如果有）
                            if (edu.getMajor() != null) {
                                eduItem.append("，").append(edu.getMajor());
                            }
                            eduItem.append("）");
                        }
                        // 多条教育经历用分号分隔
                        if (educationSb.length() > 0) {
                            educationSb.append("；");
                        }
                        educationSb.append(eduItem);
                    }
                }
            }
            String education = educationSb.length() > 0 ? educationSb.toString() : "无";

            // 3. 处理工作经验
            String experience = "无";
            if (boleResumes.getExperience() != null) {
                experience = boleResumes.getExperience();
            } else if (boleResumes.getWorkExperiences() != null && !boleResumes.getWorkExperiences().isEmpty()) {
                StringBuilder expSb = new StringBuilder();
                for (BoleResumeWork work : boleResumes.getWorkExperiences()) {
                    if (work != null && work.getPosition() != null) {
                        if (expSb.length() > 0) {
                            expSb.append("；");
                        }
                        expSb.append(work.getPosition());
                        if (work.getCompany() != null) {
                            expSb.append("（").append(work.getCompany()).append("）");
                        }
                    }
                }
                experience = expSb.length() > 0 ? expSb.toString() : "无";
            }

            // 4. 处理专业（从第一条教育经历中提取，若存在）
            String major = "无";
            if (boleResumes.getEducations() != null && !boleResumes.getEducations().isEmpty()) {
                BoleResumeEducation firstEdu = boleResumes.getEducations().get(0);
                if (firstEdu != null && firstEdu.getMajor() != null) {
                    major = firstEdu.getMajor();
                }
            }

            // 5. 处理目标岗位
            String target = boleResumes.getJobTarget() != null ? boleResumes.getJobTarget() : "无";

            // 6. 处理项目经验（新增）
            StringBuilder projectsSb = new StringBuilder();
            if (boleResumes.getProjects() != null && !boleResumes.getProjects().isEmpty()) {
                int projectIndex = 1;
                for (BoleResumeProject project : boleResumes.getProjects()) {
                    if (project != null && project.getName() != null) {
                        // 项目序号
                        projectsSb.append("项目").append(projectIndex).append("：");

                        // 项目名称
                        projectsSb.append(project.getName());

                        // 角色（如果有）
                        if (project.getRole() != null) {
                            projectsSb.append("，担任").append(project.getRole());
                        }

                        // 主要成就（如果有）
                        if (project.getAchievements() != null) {
                            projectsSb.append("，成就：").append(project.getAchievements());
                        }

                        // 多个项目用分号分隔
                        projectsSb.append("；");
                        projectIndex++;
                    }
                }
                // 移除最后一个分号
                if (projectsSb.length() > 0) {
                    projectsSb.setLength(projectsSb.length() - 1);
                }
            }
            String projects = projectsSb.length() > 0 ? projectsSb.toString() : "无";
            String prompt =
                    "简历信息：技能有%s，教育程度有%s，工作经验有%s，专业有%s，目标岗位有%s，项目经验有%s";
            prompt = String.format(prompt, skills, education, experience, major, target, projects);
            // API地址和密钥（请替换为实际值）
            String url = "https://maas-cn-southwest-2.modelarts-maas.com/v1/infers/8a062fd4-7367-4ab4-a936-5eeb8fb821c4/v1/chat/completions";
            String apiKey = "pMEYg6YUYvsADoCBCKpQi2o-AQYuffsxCGEHVyemh0aCAucWCF_uUE07gbYEDnNex_xfvyEykiWlwVQlekfo1g";  // 替换为实际API Key

            // 创建忽略SSL证书验证的OkHttpClient
            OkHttpClient client = createUnsafeOkHttpClient();
            String escapedPrompt = prompt.replace("\"", "\\\"");
            // 构建请求JSON数据
            String jsonBody = "{" +
                    "\"model\":\"DeepSeek-R1\"," +
                    "\"messages\": [" +
                    "    {\"role\": \"system\", \"content\": \"你只是一个分析的工具，而不是聊天的工具，依据简历推荐3个岗位，须给出json结构，给出jobName和reason，不要给出多余的标记字符什么json之类的，我要直接用回答做JSONObject.parseObject()解析,格式:[{jobName:xxx,reason:xxx},{jobName:xxx,reason:xxx},{jobName:xxx,reason:xxx}]\"}," +
                    "    {\"role\": \"user\", \"content\": \" "+escapedPrompt+"\"}" +
                    "  ]" +
                    "}";

            // 构建请求体
            RequestBody requestBody = RequestBody.create(
                    MediaType.parse("application/json; charset=utf-8"),
                    jsonBody

            );

            // 构建请求
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Authorization", "Bearer " + apiKey)
                    .post(requestBody)

                    .build();
            JSONObject map = null;

            // 发送请求并处理响应
            try (Response response = client.newCall(request).execute()) {
                System.out.println("响应状态码: " + response.code());
                ResponseBody body = response.body();
                if (body != null) {
                    String responseBodyString = body.string();
                    System.out.println("响应内容: " + responseBodyString);

                    // 1. 解析外层完整响应JSON
                    JSONObject outerJson = JSONObject.parseObject(responseBodyString);

                    // 2. 提取choices数组（取第一个元素）
                    JSONArray choices = outerJson.getJSONArray("choices");
                    if (!choices.isEmpty()) {
                        JSONObject firstChoice = choices.getJSONObject(0);

                        // 3. 提取message中的content（目标数组在这里）
                        JSONObject message = firstChoice.getJSONObject("message");
                        String content = message.getString("content");

                        // 4. 解析content中的JSON数组（注意用JSONArray而非JSONObject）
//                        JSONArray jobArray = JSONArray.parseArray(content);

                        // 此时jobArray就是你需要的岗位数组，可直接使用
//                        System.out.println("提取到的岗位数组: " + jobArray);

                            // 保存预测结果
                            if (predictionRecord == null) {
                                predictionRecord = new BoleScriptPredictionRecord();
                                predictionRecord.setUserId(userId);
                                predictionRecord.setPredictionTime(new Date());
                                predictionRecord.setPredictionResult(String.valueOf(content));
                                predictionRecord.setPredictionInfo(prompt);
                                predictionRecord.setRemark(String.valueOf(message));
                                boleScriptPredictionRecordMapper.insertBoleScriptPredictionRecord(predictionRecord);
                            } else {
                                predictionRecord.setPredictionResult(content);
                                predictionRecord.setPredictionInfo(prompt);
                                predictionRecord.setRemark(String.valueOf(message));
                                predictionRecord.setPredictionTime(new Date());
                                boleScriptPredictionRecordMapper.updateBoleScriptPredictionRecord(predictionRecord);
                            }


                    }
                }
            } catch (IOException e) {
                if (predictionRecord == null) {
                    predictionRecord = new BoleScriptPredictionRecord();
                    predictionRecord.setPredictionResult("[{\"jobName\":\"预测失败,\"\"reason\":\"系统错误\"}]");
                    predictionRecord.setUserId(userId);
                    predictionRecord.setPredictionTime(new Date());
                    predictionRecord.setPredictionInfo(prompt);
                    predictionRecord.setRemark("预测失败"+e.getMessage());
                    boleScriptPredictionRecordMapper.insertBoleScriptPredictionRecord(predictionRecord);
                } else {
                    predictionRecord.setPredictionResult("[{\"jobName\":\"预测失败,\"\"reason\":\"系统错误\"}]");
                    predictionRecord.setPredictionInfo(prompt);
                    predictionRecord.setRemark("预测失败"+e.getMessage());
                    predictionRecord.setPredictionTime(new Date());
                    boleScriptPredictionRecordMapper.updateBoleScriptPredictionRecord(predictionRecord);
                }
                e.printStackTrace();
            }
            logger.info("用户[{}]的预测prompt: {}", userId, jsonBody);

            logger.info("用户[{}]岗位预测完成", userId);

        } catch (Exception e) {
            System.out.println(userId);
            logger.error("用户[{}]岗位预测失败", userId, e);
        }
    }
    @Async("asyncExecutor") // 指定使用名为 asyncExecutor 的线程池
    @Override
    @Transactional
    public void  executeResumeAnalysis(Long userId){
        try {
            BoleScriptPredictionRecord2 predictionRecord = boleScriptPredictionRecordMapper2.selectBoleScriptPredictionRecordByUserId(userId);
            ResumeDTO boleResumes = resumeService.getResume(userId);

            if (boleResumes == null) {
                logger.warn("用户[{}]未找到简历信息，无法进行岗位预测", userId);
                return;
            }

            // 构建prompt（基于实际实体类结构）
            // 1. 处理技能（BoleResumeSkills列表，提取skillName）
            StringBuilder skillsSb = new StringBuilder();
            if (boleResumes.getSkills() != null && !boleResumes.getSkills().isEmpty()) {
                for (BoleResumeSkills skill : boleResumes.getSkills()) {
                    if (skill != null && skill.getSkillName() != null) {
                        if (skillsSb.length() > 0) {
                            skillsSb.append("、"); // 用顿号分隔多个技能
                        }
                        skillsSb.append(skill.getSkillName());
                    }
                }
            }
            String skills = skillsSb.length() > 0 ? skillsSb.toString() : "无";

            // 2. 处理教育经历（BoleResumeEducation列表，拼接学历、学校、专业）
            StringBuilder educationSb = new StringBuilder();
            if (boleResumes.getEducations() != null && !boleResumes.getEducations().isEmpty()) {
                for (BoleResumeEducation edu : boleResumes.getEducations()) {
                    if (edu != null) {
                        // 跳过空的教育记录
                        if (edu.getDegree() == null && edu.getSchool() == null) {
                            continue;
                        }
                        // 拼接格式：学历（学校，专业）
                        StringBuilder eduItem = new StringBuilder();
                        if (edu.getDegree() != null) {
                            eduItem.append(edu.getDegree());
                        }
                        if (edu.getSchool() != null) {
                            eduItem.append("（").append(edu.getSchool());
                            // 补充专业（如果有）
                            if (edu.getMajor() != null) {
                                eduItem.append("，").append(edu.getMajor());
                            }
                            eduItem.append("）");
                        }
                        // 多条教育经历用分号分隔
                        if (educationSb.length() > 0) {
                            educationSb.append("；");
                        }
                        educationSb.append(eduItem);
                    }
                }
            }
            String education = educationSb.length() > 0 ? educationSb.toString() : "无";

            // 3. 处理工作经验
            String experience = "无";
            if (boleResumes.getExperience() != null) {
                experience = boleResumes.getExperience();
            } else if (boleResumes.getWorkExperiences() != null && !boleResumes.getWorkExperiences().isEmpty()) {
                StringBuilder expSb = new StringBuilder();
                for (BoleResumeWork work : boleResumes.getWorkExperiences()) {
                    if (work != null && work.getPosition() != null) {
                        if (expSb.length() > 0) {
                            expSb.append("；");
                        }
                        expSb.append(work.getPosition());
                        if (work.getCompany() != null) {
                            expSb.append("（").append(work.getCompany()).append("）");
                        }
                    }
                }
                experience = expSb.length() > 0 ? expSb.toString() : "无";
            }

            // 4. 处理专业（从第一条教育经历中提取，若存在）
            String major = "无";
            if (boleResumes.getEducations() != null && !boleResumes.getEducations().isEmpty()) {
                BoleResumeEducation firstEdu = boleResumes.getEducations().get(0);
                if (firstEdu != null && firstEdu.getMajor() != null) {
                    major = firstEdu.getMajor();
                }
            }

            // 5. 处理目标岗位
            String target = boleResumes.getJobTarget() != null ? boleResumes.getJobTarget() : "无";

            // 6. 处理项目经验（新增）
            StringBuilder projectsSb = new StringBuilder();
            if (boleResumes.getProjects() != null && !boleResumes.getProjects().isEmpty()) {
                int projectIndex = 1;
                for (BoleResumeProject project : boleResumes.getProjects()) {
                    if (project != null && project.getName() != null) {
                        // 项目序号
                        projectsSb.append("项目").append(projectIndex).append("：");

                        // 项目名称
                        projectsSb.append(project.getName());

                        // 角色（如果有）
                        if (project.getRole() != null) {
                            projectsSb.append("，担任").append(project.getRole());
                        }

                        // 主要成就（如果有）
                        if (project.getAchievements() != null) {
                            projectsSb.append("，成就：").append(project.getAchievements());
                        }

                        // 多个项目用分号分隔
                        projectsSb.append("；");
                        projectIndex++;
                    }
                }
                // 移除最后一个分号
                if (projectsSb.length() > 0) {
                    projectsSb.setLength(projectsSb.length() - 1);
                }
            }
            String projects = projectsSb.length() > 0 ? projectsSb.toString() : "无";

            // 7. 构建最终prompt（已添加项目经验）
            String prompt =
                    "简历信息：技能有%s，教育程度有%s，工作经验有%s，专业有%s，目标岗位有%s，项目经验有%s";

            // API地址和密钥（请替换为实际值）
            String url = "https://maas-cn-southwest-2.modelarts-maas.com/v1/infers/8a062fd4-7367-4ab4-a936-5eeb8fb821c4/v1/chat/completions";
            String apiKey = "pMEYg6YUYvsADoCBCKpQi2o-AQYuffsxCGEHVyemh0aCAucWCF_uUE07gbYEDnNex_xfvyEykiWlwVQlekfo1g";  // 替换为实际API Key

            // 创建忽略SSL证书验证的OkHttpClient
            OkHttpClient client = createUnsafeOkHttpClient();
            String escapedPrompt = prompt.replace("\"", "\\\"");
            // 构建请求JSON数据
            String jsonBody = "{" +
                    "\"model\":\"DeepSeek-R1\"," +
                    "\"messages\": [" +
                    "    {\"role\": \"system\", \"content\": \"你只是一个分析的工具，而不是聊天的工具，依据这份简历，给这个人打分！须给出json结构，给出title和score（纯数字60-100），不要给出多余的标记字符什么json之类的，我要直接用回答做JSONObject.parseObject()解析,格式:[{title:'学习能力',score:xxx},{title:'沟通能力',score:xxx},{title:'沟通协调能力',score:xxx},{title:'成就动机',score:xxx}]\"}," +
                    "    {\"role\": \"user\", \"content\": \" "+escapedPrompt+"\"}" +
                    "  ]" +
                    "}";

            // 构建请求体
            RequestBody requestBody = RequestBody.create(
                    MediaType.parse("application/json; charset=utf-8"),
                    jsonBody

            );

            // 构建请求
            Request request = new Request.Builder()
                    .url(url)
                    .addHeader("Content-Type", "application/json")
                    .addHeader("Authorization", "Bearer " + apiKey)
                    .post(requestBody)

                    .build();
            JSONObject map = null;

            // 发送请求并处理响应
            try (Response response = client.newCall(request).execute()) {
                System.out.println("响应状态码: " + response.code());
                ResponseBody body = response.body();
                if (body != null) {
                    String responseBodyString = body.string();
                    System.out.println("响应内容: " + responseBodyString);

                    // 1. 解析外层完整响应JSON
                    JSONObject outerJson = JSONObject.parseObject(responseBodyString);

                    // 2. 提取choices数组（取第一个元素）
                    JSONArray choices = outerJson.getJSONArray("choices");
                    if (!choices.isEmpty()) {
                        JSONObject firstChoice = choices.getJSONObject(0);

                        // 3. 提取message中的content（目标数组在这里）
                        JSONObject message = firstChoice.getJSONObject("message");
                        String content = message.getString("content");

                            // 保存预测结果
                            if (predictionRecord == null) {
                                predictionRecord = new BoleScriptPredictionRecord2();
                                predictionRecord.setUserId(userId);
                                predictionRecord.setPredictionTime(new Date());
                                predictionRecord.setPredictionResult(content);
                                predictionRecord.setPredictionInfo(prompt);
                                predictionRecord.setRemark(String.valueOf(message));
                                boleScriptPredictionRecordMapper2.insertBoleScriptPredictionRecord2(predictionRecord);
                            } else {
                                predictionRecord.setPredictionResult(content);
                                predictionRecord.setPredictionInfo(prompt);
                                predictionRecord.setRemark(String.valueOf(message));
                                predictionRecord.setPredictionTime(new Date());
                                boleScriptPredictionRecordMapper2.updateBoleScriptPredictionRecord2(predictionRecord);
                            }


                    }
                }
            } catch (IOException e) {
                // 保存预测结果
                if (predictionRecord == null) {
                    predictionRecord = new BoleScriptPredictionRecord2();
                    predictionRecord.setUserId(userId);
                    predictionRecord.setPredictionTime(new Date());
                    predictionRecord.setPredictionResult("[]");
                    predictionRecord.setPredictionInfo("岗位预测信息");
                    predictionRecord.setRemark(e.getMessage());
                    boleScriptPredictionRecordMapper2.insertBoleScriptPredictionRecord2(predictionRecord);
                } else {
                    predictionRecord.setPredictionResult("[]");
                    predictionRecord.setPredictionInfo(prompt);
                    predictionRecord.setRemark(e.getMessage());
                    predictionRecord.setPredictionTime(new Date());
                    boleScriptPredictionRecordMapper2.updateBoleScriptPredictionRecord2(predictionRecord);
                }
                e.printStackTrace();
            }

            logger.info("用户[{}]岗位预测完成", userId);

        } catch (Exception e) {
            logger.error("用户[{}]岗位预测失败", userId, e);
        }
    }
    // 创建忽略SSL证书验证的OkHttpClient（仅用于测试环境，生产环境不建议使用）
    // 你原有的“忽略SSL的OkHttpClient创建方法”，超时加在这里！
    private static OkHttpClient createUnsafeOkHttpClient() {
        try {
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] chain, String authType) {}
                        @Override
                        public void checkServerTrusted(X509Certificate[] chain, String authType) {}
                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[0];
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new SecureRandom());
            final HostnameVerifier hostnameVerifier = (hostname, session) -> true;

            // 👇👇 超时配置加在这里！！！
            return new OkHttpClient.Builder()
                    // 1. 连接超时：建立TCP连接的最大时间（30秒）
                    .connectTimeout(30, TimeUnit.SECONDS)
                    // 2. 读取超时：连接后等服务器响应的最大时间（大模型用60秒，避免超时）
                    .readTimeout(60, TimeUnit.SECONDS)
                    // 3. 写入超时：向服务器发请求体的最大时间（15秒足够）
                    .writeTimeout(15, TimeUnit.SECONDS)
                    // 你原有的SSL相关配置（测试用）
                    .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustAllCerts[0])
                    .hostnameVerifier(hostnameVerifier)
                    .build(); // 最终构建客户端
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
